﻿using System;
using System.IO;
using System.Collections.Generic;
using FLMScan.Geometry;

namespace FLMScan
{
    class ObjectData
    {
        private Dictionary<int, List<FlmPoint>> worldPoints;

        public ObjectData()
        {
            worldPoints = new Dictionary<int, List<FlmPoint>>();
        }

        public void AddObjectPoints(double angle, List<FlmPoint> points)
        {
            // Ugly solution, but ok for the moment:
            // multiply angle by 10 to avoid adding 
            // multiple points for the same rounded angle
            int angleInInts = (int)(angle * 10.0);
            worldPoints.Add(angleInInts, points);
        }

        public void Serialize(String fileName)
        {
            SerializeText(fileName);
            SerializePly(fileName);
        }

        private void SerializeText(string fileName)
        {
            TextWriter textWriter = new StreamWriter(fileName + ".txt");

            foreach (int angle in worldPoints.Keys)
            {
                List<FlmPoint> points;
                if (worldPoints.TryGetValue(angle, out points))
                {
                    foreach (FlmPoint v in points)
                    {                        
                        string coordinates = v.X.ToString("f") + ";" + v.Y.ToString("f") + ";" + v.Z.ToString("f");
                        string replacedComma = coordinates.Replace(',', '.');
                        textWriter.WriteLine(replacedComma);
                    }
                }
            }
                        
            textWriter.Flush();
            textWriter.Close();
            textWriter.Dispose();
        }

        private void SerializePly(string fileName)
        {
            TextWriter textWriter = new StreamWriter(fileName + ".ply");

            int vertexCount = 0;
            foreach (int angle in worldPoints.Keys)
            {
                List<FlmPoint> points;
                if (worldPoints.TryGetValue(angle, out points))
                {
                    vertexCount += points.Count;
                }
            }

            WritePlyHeader(textWriter, vertexCount);

            foreach (int angle in worldPoints.Keys)
            {
                List<FlmPoint> points;
                if (worldPoints.TryGetValue(angle, out points))
                {
                    foreach (FlmPoint v in points)
                    {
                        string coordinates = v.X.ToString("f") + " " + v.Y.ToString("f") + " " + v.Z.ToString("f");
                        string replacedComma = coordinates.Replace(',', '.');
                        textWriter.WriteLine(replacedComma);
                    }
                }
            }

            textWriter.Flush();
            textWriter.Close();
            textWriter.Dispose();
        }

        private void WritePlyHeader(TextWriter textWriter, int vertexCount)
        {
            textWriter.WriteLine("ply");
            textWriter.WriteLine("format ascii 1.0");
            textWriter.WriteLine("comment FLMScan object data");
            textWriter.WriteLine("comment Powered by FabLab Munich");
            textWriter.WriteLine("comment");
            textWriter.WriteLine("element vertex " + vertexCount);
            textWriter.WriteLine("property float x");
            textWriter.WriteLine("property float y");
            textWriter.WriteLine("property float z");
            textWriter.WriteLine("end_header");
        }
    }
}
